tool
extends EditorInspectorPlugin

class MyVector3Edit:
	extends HBoxContainer

	const labels = ["x", "y", "z"]

	var value: Vector3 = Vector3(0, 0, 0) setget set_value
	var spin: Array = []
	var updating: bool = false

	signal value_changed(p_value)

	func _value_changed(p_value):
		if updating:
			return

		value = Vector3(spin[0].value, spin[1].value, spin[2].value)
		emit_signal("value_changed", value)

	func _init():
		for i in range(3):
			var ctl: EditorSpinSlider = EditorSpinSlider.new()
			spin.push_back(ctl)
			ctl.flat = true
			ctl.label = labels[i]
			add_child(ctl)
			ctl.connect("value_changed", self, "_value_changed")
			ctl.set_h_size_flags(SIZE_EXPAND_FILL)

	func add_focusable(p_owner: EditorProperty):
		for i in range(3):
			p_owner.add_focusable(spin[i])

	func set_value(p_value: Vector3):
		updating = true
		value = p_value
		for i in range(3):
			if spin[i].value != p_value[i]:
				spin[i].value = p_value[i]
		updating = false

	func setup(p_min: float, p_max: float, p_step: float):
		for i in range(3):
			spin[i].min_value = p_min
			spin[i].max_value = p_max
			spin[i].step = p_step
			spin[i].allow_greater = true
			spin[i].allow_lesser = true

class PolyhedronPositionEditor:
	extends EditorProperty

	var updating = false
	var id_edit: LineEdit = LineEdit.new()
	var pos_edit: MyVector3Edit = MyVector3Edit.new()
	var rot_edit: OptionButton = OptionButton.new()
	var checkboxes: Array = []

	const flag_names = [ "X", "Y", "Z" ]
	const flag_names_2 = [ "XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX" ]
	const flag_values_2 = [ PolyhedronPosition.ROT_XYZ,
		PolyhedronPosition.ROT_YZX,
		PolyhedronPosition.ROT_ZXY,
		PolyhedronPosition.ROT_XZY,
		PolyhedronPosition.ROT_YXZ,
		PolyhedronPosition.ROT_ZYX,
	]
	const button_texts = [
		"Rotate Left", "Rotate Right",
		"Rotate Up", "Rotate Down",
		"Rotate CW", "Rotate CCW",
	]
	const rotate_directions = [
		Vector3(-1, 0, 0), Vector3(1, 0, 0),
		Vector3(0, 0, -1), Vector3(0, 0, 1),
		Vector3(0, -1, 0), Vector3(0, 1, 0),
	]


	func _prop_changed(p_value):
		_rot_button_pressed(Vector3(0, 0, 0))

	func _rot_button_pressed(p_dir: Vector3):
		if updating:
			return

		var flags: int = 0
		for i in range(checkboxes.size()):
			if checkboxes[i].pressed:
				flags |= 1 << i
		var idx = clamp(rot_edit.get_selected_id(), 0, flag_values_2.size())
		flags |= flag_values_2[idx]

		emit_changed(get_edited_property(), {
			"map_data_name": id_edit.text,
			"position": pos_edit.value,
			"flags": PolyhedronPosition.rotate_flags(flags, p_dir)
			})

	func _init():
		var vbc: VBoxContainer = VBoxContainer.new()

		var hbc: HBoxContainer = HBoxContainer.new()
		var lbl: Label = Label.new()
		lbl.text = "MapData Name"
		lbl.set_h_size_flags(SIZE_EXPAND_FILL)
		hbc.add_child(lbl)
		id_edit.set_h_size_flags(SIZE_EXPAND_FILL)
		hbc.add_child(id_edit)
		vbc.add_child(hbc)

		lbl = Label.new()
		lbl.text = "Position"
		vbc.add_child(lbl)
		vbc.add_child(pos_edit)

		hbc = HBoxContainer.new()
		lbl = Label.new()
		lbl.text = "Rotation"
		lbl.set_h_size_flags(SIZE_EXPAND_FILL)
		hbc.add_child(lbl)
		for s in flag_names_2:
			rot_edit.add_item(s)
		rot_edit.set_h_size_flags(SIZE_EXPAND_FILL)
		hbc.add_child(rot_edit)
		vbc.add_child(hbc)

		hbc = HBoxContainer.new()
		lbl = Label.new()
		lbl.text = "Invert"
		lbl.set_h_size_flags(SIZE_EXPAND_FILL)
		hbc.add_child(lbl)
		for i in range(3):
			var obj: CheckBox = CheckBox.new()
			obj.text = flag_names[i]
			obj.set_h_size_flags(SIZE_EXPAND_FILL)
			hbc.add_child(obj)
			checkboxes.push_back(obj)
			obj.connect("toggled", self, "_prop_changed")
		vbc.add_child(hbc)

		var gc: GridContainer = GridContainer.new()
		gc.columns = 2
		for i in range(6):
			var obj: Button = Button.new()
			obj.text = button_texts[i]
			obj.set_h_size_flags(SIZE_EXPAND_FILL)
			gc.add_child(obj)
			obj.connect("pressed", self, "_rot_button_pressed", [rotate_directions[i]])
		gc.set_h_size_flags(SIZE_EXPAND_FILL)
		vbc.add_child(gc)

		add_child(vbc)
		set_bottom_editor(vbc)

		add_focusable(id_edit)
		pos_edit.add_focusable(self)
		pos_edit.setup(-100, 100, 1)
		for obj in checkboxes:
			add_focusable(obj)

		id_edit.connect("text_changed", self, "_prop_changed")
		pos_edit.connect("value_changed", self, "_prop_changed")
		rot_edit.connect("item_selected", self, "_prop_changed")

	func update_property():
		var new_value = get_edited_object()[get_edited_property()]
		updating = true
		if id_edit.text != new_value["map_data_name"]:
			id_edit.text = new_value["map_data_name"]
		if pos_edit.value != new_value["position"]:
			pos_edit.value = new_value["position"]
		var flags: int = new_value["flags"]
		for i in range(checkboxes.size()):
			checkboxes[i].pressed = (flags & (1 << i)) != 0
		flags &= PolyhedronPosition.ROT_MASK
		rot_edit.select(0)
		for i in range(flag_values_2.size()):
			if flags == flag_values_2[i]:
				rot_edit.select(i)
				break
		updating = false

func can_handle(object):
	return object is CuboidPolyhedron

func parse_property(object, type, path, hint, hint_text, usage):
	if type == TYPE_DICTIONARY and path.ends_with("map_position"):
		add_property_editor(path, PolyhedronPositionEditor.new())
		return true

	return false
